В предыдущих шагах мы делали шаги на Win32 API и очень быстро пробежали по основным возможностям OpenGL.
А как извесно, если быстро бежать, то ничего вокруг не увидишь. Вот теперь, хорошо пробежавшись, начнем медленно и внимательно изучать команды OpenGL.
Но чтобы было не так скучно мы будем использовать не Win32 API, а MFC.
В шаге 15 мы посмотрели как пишется программа c OpenGL+MFC в виде диалога, теперь посмотрим как сделать такую же програмку в модели Doc-View.
Прежде всего создаем проект с помощью MFC Wizard и класс View наследуем от CView (хотя можно и от других классов, но в этом просто нет смысла).
В файл stdafx.h добавим заголовочные файлы OpenGL, а в Project->Settings добавим библиотеки OpenGL. Как вы помните из приложений на Win32 API необходимо задать стиль окна. Это можно сделать в функции PreCreateWindow(...). Например так:
BOOL CExampleView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
Затем нам надо установить формат пикселя и создать контекст рендеринга. Это можно сделать в обработчике WM_CREATE:
int CExampleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
PIXELFORMATDESCRIPTOR pfd;
int iPixelFormat;
CDC *pDC;
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
pDC = GetDC();
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cDepthBits = 16;
iPixelFormat = ChoosePixelFormat(pDC->m_hDC, &pfd);
SetPixelFormat(pDC->m_hDC, iPixelFormat, &pfd);
m_hglrc = wglCreateContext(pDC->m_hDC);
wglMakeCurrent(pDC->m_hDC, m_hglrc);
ReleaseDC(pDC);
return 0;
}
Не забудьте в описание класса (желательно в раздел private или protected) добавить переменную:
private: HGLRC m_hglrc;
Как вы понимаете это и есть наш контекст рендеринга.
Перед выходом из программы желательно удалить ранее полученный контекст рендеринга. Давайте сделаем это в обработчике WM_DESTROY:
void CExampleView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
wglMakeCurrent(NULL, NULL);
}
Теперь, если вся подготовка прошла удачно. Начинаем что-нибудь рисовать. Разумнее всего (для статических картинок) это сделать в обработчике OnDraw:
void CExampleView::OnDraw(CDC* pDC)
{
CRect clientRect;
CExampleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
GetClientRect(&clientRect);
glViewport(0, 0, clientRect.right, clientRect.bottom);
glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона
glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета
glPointSize (20); // размер точек
glColor3f (1.0, 0.0, 0.5); // текущий цвет примитивов
glBegin (GL_POINTS);
glVertex2f (-1, -1);
glVertex2f (-1, 1);
glVertex2f (0, 0);
glVertex2f (1, -1);
glVertex2f (1, 1);
glEnd();
}
Программа рисует 5 "толстых" точек. Легко понять, что толщина точек задается командой glPointSize(GLint iSize);
Если вы не используете специальных команд преобразования видовых координат, то библиотека настраивается так, что система координат начинается в центре экрана и простирается от -1 до +1 по X и от -1 до +1 по Y.